{
 "cells": [
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-02-26T07:48:02.746516Z",
     "start_time": "2025-02-26T07:47:52.747066Z"
    }
   },
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.1\n",
      "torch 2.6.0+cu118\n",
      "cuda:0\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T09:13:18.726202Z",
     "start_time": "2025-02-26T09:13:16.827653Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from pathlib import Path\n",
    "\n",
    "DATA_DIR = Path(\"cifar-10\")\n",
    "\n",
    "train_lables_file = DATA_DIR / \"trainLabels.csv\"\n",
    "test_csv_file = DATA_DIR / \"sampleSubmission.csv\" #测试集模板csv文件\n",
    "train_folder = DATA_DIR / \"train\"\n",
    "test_folder = DATA_DIR / \"test\"\n",
    "\n",
    "#所有的类别\n",
    "class_names = [\n",
    "    'airplane',\n",
    "    'automobile',\n",
    "    'bird',\n",
    "    'cat',\n",
    "    'deer',\n",
    "    'dog',\n",
    "    'frog',\n",
    "    'horse',\n",
    "    'ship',\n",
    "    'truck',\n",
    "]\n",
    "\n",
    "def parse_csv_file(filepath, folder): #filepath:csv文件路径，folder:图片所在文件夹\n",
    "    \"\"\"Parses csv files into (filename(path), label) format\"\"\"\n",
    "    results = []\n",
    "    #读取所有行\n",
    "    with open(filepath, 'r') as f:\n",
    "#         lines = f.readlines()  为什么加[1:]，可以试这个\n",
    "        #第一行不需要，因为第一行是标题\n",
    "        lines = f.readlines()[1:] \n",
    "    for line in lines:#依次去取每一行\n",
    "        image_id, label_str = line.strip('\\n').split(',') #图片id 和标签分离\n",
    "        image_full_path = folder / f\"{image_id}.png\"#文件路径\n",
    "        results.append((image_full_path, label_str)) #得到对应图片的路径和分类\n",
    "    return results\n",
    "\n",
    "#解析对应的文件夹\n",
    "train_labels_info = parse_csv_file(train_lables_file, train_folder)\n",
    "test_csv_info = parse_csv_file(test_csv_file, test_folder)\n",
    "#打印\n",
    "import pprint\n",
    "pprint.pprint(train_labels_info[0:5])\n",
    "pprint.pprint(test_csv_info[0:5])\n",
    "print(len(train_labels_info), len(test_csv_info))"
   ],
   "id": "5399b7907adc34a0",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(WindowsPath('cifar-10/train/1.png'), 'frog'),\n",
      " (WindowsPath('cifar-10/train/2.png'), 'truck'),\n",
      " (WindowsPath('cifar-10/train/3.png'), 'truck'),\n",
      " (WindowsPath('cifar-10/train/4.png'), 'deer'),\n",
      " (WindowsPath('cifar-10/train/5.png'), 'automobile')]\n",
      "[(WindowsPath('cifar-10/test/1.png'), 'cat'),\n",
      " (WindowsPath('cifar-10/test/2.png'), 'cat'),\n",
      " (WindowsPath('cifar-10/test/3.png'), 'cat'),\n",
      " (WindowsPath('cifar-10/test/4.png'), 'cat'),\n",
      " (WindowsPath('cifar-10/test/5.png'), 'cat')]\n",
      "50000 300000\n"
     ]
    }
   ],
   "execution_count": 6
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T09:13:20.793708Z",
     "start_time": "2025-02-26T09:13:20.734520Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# train_df = pd.DataFrame(train_labels_info)\n",
    "train_df = pd.DataFrame(train_labels_info[0:45000]) # 取前45000张图片作为训练集\n",
    "valid_df = pd.DataFrame(train_labels_info[45000:]) # 取后5000张图片作为验证集\n",
    "test_df = pd.DataFrame(test_csv_info)\n",
    "\n",
    "train_df.columns = ['filepath', 'class']\n",
    "valid_df.columns = ['filepath', 'class']\n",
    "test_df.columns = ['filepath', 'class']\n",
    "\n",
    "print(train_df.head())\n",
    "print(valid_df.head())\n",
    "print(test_df.head())"
   ],
   "id": "19d84b3dc7539a04",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "               filepath       class\n",
      "0  cifar-10\\train\\1.png        frog\n",
      "1  cifar-10\\train\\2.png       truck\n",
      "2  cifar-10\\train\\3.png       truck\n",
      "3  cifar-10\\train\\4.png        deer\n",
      "4  cifar-10\\train\\5.png  automobile\n",
      "                   filepath       class\n",
      "0  cifar-10\\train\\45001.png       horse\n",
      "1  cifar-10\\train\\45002.png  automobile\n",
      "2  cifar-10\\train\\45003.png        deer\n",
      "3  cifar-10\\train\\45004.png  automobile\n",
      "4  cifar-10\\train\\45005.png    airplane\n",
      "              filepath class\n",
      "0  cifar-10\\test\\1.png   cat\n",
      "1  cifar-10\\test\\2.png   cat\n",
      "2  cifar-10\\test\\3.png   cat\n",
      "3  cifar-10\\test\\4.png   cat\n",
      "4  cifar-10\\test\\5.png   cat\n"
     ]
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T09:13:27.068694Z",
     "start_time": "2025-02-26T09:13:27.061415Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from PIL import Image\n",
    "from torch.utils.data import Dataset, DataLoader\n",
    "from torchvision import transforms\n",
    "\n",
    "class Cifar10Dataset(Dataset):\n",
    "    df_map = {\n",
    "        \"train\": train_df,\n",
    "        \"eval\": valid_df,\n",
    "        \"test\": test_df\n",
    "    }\n",
    "    label_to_idx = {label: idx for idx, label in enumerate(class_names)} # 类别映射为idx\n",
    "    idx_to_label = {idx: label for idx, label in enumerate(class_names)} # idx映射为类别,为了test测试集使用\n",
    "    def __init__(self, mode, transform=None):\n",
    "        self.df = self.df_map.get(mode, None) # 获取对应模式的df，不同字符串对应不同模式\n",
    "        if self.df is None:\n",
    "            raise ValueError(\"mode should be one of train, val, test, but got {}\".format(mode))\n",
    "        # assert self.df, \"df is None\"\n",
    "        self.transform = transform\n",
    "        \n",
    "    def __getitem__(self, index):\n",
    "        img_path, label = self.df.iloc[index] # 获取图片路径和标签\n",
    "        img = Image.open(img_path).convert('RGB')\n",
    "        # # img 转换为 channel first\n",
    "        # img = img.transpose((2, 0, 1))\n",
    "        # transform\n",
    "        img = self.transform(img) # 数据增强\n",
    "        # label 转换为 idx\n",
    "        label = self.label_to_idx[label]\n",
    "        return img, label\n",
    "    \n",
    "    def __len__(self):\n",
    "        return self.df.shape[0] # 返回df的行数,样本数\n",
    "    \n",
    "IMAGE_SIZE = 32\n",
    "mean, std = [0.4914, 0.4822, 0.4465], [0.247, 0.243, 0.261]\n",
    "\n",
    "transforms_train = transforms.Compose([\n",
    "        # resize\n",
    "        transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)), #缩放\n",
    "        # random rotation 40\n",
    "        transforms.RandomRotation(40), #随机旋转\n",
    "        # horizaontal flip\n",
    "        transforms.RandomHorizontalFlip(),  #随机水平翻转\n",
    "        transforms.ToTensor(), #转换为tensor\n",
    "        # transforms.Normalize(mean, std) #标准化\n",
    "    ]) #数据增强\n",
    "\n",
    "transforms_eval = transforms.Compose([\n",
    "        # resize\n",
    "        transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),\n",
    "        transforms.ToTensor(),\n",
    "        transforms.Normalize(mean, std)\n",
    "    ])\n",
    "# ToTensor还将图像的维度从[height, width, channels]转换为[channels, height, width]。\n",
    "train_ds = Cifar10Dataset(\"train\", transforms_train)\n",
    "eval_ds = Cifar10Dataset(\"eval\", transforms_eval)"
   ],
   "id": "e36c3a0d9beadf78",
   "outputs": [],
   "execution_count": 9
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
